﻿using NovoDataBase;
using NovoSerDes.A2B.Func;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace NovoSerDes.A2B.Forms
{
    public partial class Propeties : UIForm
    {
        public string XMLPath { get; set; }
        private SerDesComm serDesComm;
        private IICMode _iicMode = IICMode.A16D16;
        private DataTable xmlData;
        public Propeties()
        {
            InitializeComponent();
            InitializeHexTextBox();
            this.combox_Addr_Width.SelectedIndex = 1;
            this.combox_Data_Width.SelectedIndex = 1;
            serDesComm = new SerDesComm();
            serDesComm.OpenDevice(0);
        }
        private void InitializeHexTextBox()
        {           
            txtbox_IICAddr.Text = "0x";
            txtbox_IICAddr.SelectionStart = txtbox_IICAddr.Text.Length;
            txtbox_IICAddr.TextChanged += HexTextBox_TextChanged;
            txtbox_IICAddr.KeyPress += HexTextBox_KeyPress;            
        }

        private void HexTextBox_TextChanged(object sender, EventArgs e)
        {
            // 确保前缀 "0x" 存在
            if (!txtbox_IICAddr.Text.StartsWith("0x"))
            {
                txtbox_IICAddr.Text = "0x" + txtbox_IICAddr.Text.Replace("0x", "");
                txtbox_IICAddr.SelectionStart = txtbox_IICAddr.Text.Length;
            }

            // 只允许数字和字母 A-F 通过验证
            string validText = "0x";
            foreach (char c in txtbox_IICAddr.Text.Substring(2))
            {
                if (IsHexChar(c))
                {
                    validText += c;
                }
            }

            if (txtbox_IICAddr.Text != validText)
            {
                txtbox_IICAddr.Text = validText;
                txtbox_IICAddr.SelectionStart = txtbox_IICAddr.Text.Length;
            }
        }

        private void HexTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            // 阻止不合法字符的输入
            if (!char.IsControl(e.KeyChar) && !IsHexChar(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        private bool IsHexChar(char c)
        {
            return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
        }

        private bool IsHexString(string input)
        {
            foreach (char c in input)
            {
                if (!Uri.IsHexDigit(c))
                {
                    return false;
                }
            }
            return true;
        }


        private void btn_openXml_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*";
                ofd.Title = "Open XML File";
                if(ofd.ShowDialog() == DialogResult.OK)
                {
                    XMLPath = ofd.FileName;
                    this.txtbox_programming_xmlfile.Text = XMLPath;
                }
            }
        }

        private void btn_Edit_Click(object sender, EventArgs e)
        {
            XmlPars xmlPars = new XmlPars();
            xmlData = xmlPars.ParsXmlFile(XMLPath);
            XmlDataGrid xmlDataGrid = new XmlDataGrid(xmlData);
            xmlDataGrid.ShowDialog();
        }

        private void btn_Read_Click(object sender, EventArgs e)
        {
            //byte _chipAddr = (byte)(this.txtbox_IICAddr.Text.ToInt() * 2);
            byte _chipAddr = 0;
            string hexInput = this.txtbox_IICAddr.Text;

            // 移除 "0x" 前缀（如果存在）
            if (hexInput.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
            {
                hexInput = hexInput.Substring(2);
            }

            // 验证输入是否为有效的十六进制字符串
            if (IsHexString(hexInput) && hexInput != "")
            {
                // 将十六进制字符串转换为整数，并乘以 2，再转换为字节
                _chipAddr = (byte)(Convert.ToInt32(hexInput, 16) * 2);
                // 这里可以使用 _chipAddr 进行后续操作
            }
           

            object regAddr = this.numeric_Address.Value;
   
            object rdData = 0;
            serDesComm.IICRead(_chipAddr, regAddr,out rdData,_iicMode);
            uint dataValue = Convert.ToUInt32(rdData);
            this.txtbox_Data.Text = "0x" +  dataValue.ToString("X");
        }

        private void btn_Write_Click(object sender, EventArgs e)
        {


            //byte _chipAddr = (byte)(this.txtbox_IICAddr.Text.ToInt()* 2);
            byte _chipAddr = 0;
            string hexInput = this.txtbox_IICAddr.Text;

            // 移除 "0x" 前缀（如果存在）
            if (hexInput.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
            {
                hexInput = hexInput.Substring(2);
            }

            // 验证输入是否为有效的十六进制字符串
            if (IsHexString(hexInput))
            {
                // 将十六进制字符串转换为整数，并乘以 2，再转换为字节
                _chipAddr = (byte)(Convert.ToInt32(hexInput, 16) * 2);
                // 这里可以使用 _chipAddr 进行后续操作
            }
            

            object regAddr = this.numeric_Address.Value;
            object regData = 0;
            if (txtbox_Data.Text.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
            {
                string data = this.txtbox_Data.Text.Substring(2);
                if (IsHexString(data))
                {
                    regData = (object)Convert.ToInt32(data,16);
                }
            }
            else
            {
                string data = this.txtbox_Data.Text;
                if (IsHexString(data))
                {
                    regData = (object)Convert.ToInt32(data, 16);
                }
            }
            

            bool ret = serDesComm.IICWrite(_chipAddr, regAddr, regData, _iicMode);
            if(ret)
            {
                ShowSuccessTip("succcessful write");
            }
        }

        private void combox_Addr_Width_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateIICMode();
        }

        private void combox_Data_Width_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateIICMode();
        }
        private void UpdateIICMode()
        {
            int addrWidth = GetWidthFromComboBox(combox_Addr_Width);
            int dataWidth = GetWidthFromComboBox(combox_Data_Width);

            _iicMode = GetIICMode(addrWidth, dataWidth);
        }

        private int GetWidthFromComboBox(UIComboBox comboBox)
        {
            switch (comboBox.SelectedItem)
            {
                case "1": return 8;
                case "2": return 16;
                case "4": return 32;
                default: return 0;
            }
        }

        private IICMode GetIICMode(int addrWidth, int dataWidth)
        {
            if (addrWidth == 8)
            {
                if (dataWidth == 8) return IICMode.A8D8;
                if (dataWidth == 16) return IICMode.A8D16;
                if (dataWidth == 32) return IICMode.A8D32;
            }
            if (addrWidth == 16)
            {
                if (dataWidth == 8) return IICMode.A16D8;
                if (dataWidth == 16) return IICMode.A16D16;
                if (dataWidth == 32) return IICMode.A16D32;
            }
            if (addrWidth == 32)
            {
                if (dataWidth == 8) return IICMode.A32D8;
                if (dataWidth == 16) return IICMode.A32D16;
                if (dataWidth == 32) return IICMode.A32D32;
            }

            return IICMode.None;
        }

        private void btn_program_Click(object sender, EventArgs e)
        {
            byte currentChipAddr = 0;
            object regAddr = 0;
            object[] datas = null;
            IICMode mode = IICMode.A16D8;

            bool ret = true;           

            XmlPars xmlPars = new XmlPars();
            xmlData = xmlPars.ParsXmlFile(XMLPath);
            IICMode _mode = IICMode.A16D8;

            foreach(DataRow row in xmlData.Rows)
            {
                if (row[0].ToString().ToLower().Contains("write"))
                {
                    _mode = GetIICMode(row[1].ToString().ToInt() * 8, row[2].ToString().ToInt() * 8);
                    currentChipAddr =(byte)(Convert.ToUInt32(row[5].ToString()) * 2);
                    regAddr = (object)Convert.ToUInt32(row[4].ToString(),16);
                    string[] hexData = row[9].ToString().Split(',');
                    datas = new object[hexData.Length];

                    if(datas.Length > 4)
                    {
                        for (int i = 0; i < hexData.Length; i++)
                        {
                            string hexValue = hexData[i].Trim();
                            datas[i] = Convert.ToInt32(hexValue, 16);
                        }
                        object[][] splitDatas = SplitArray(datas, 1024);
                        for(int i = 0; i < splitDatas.Length; i++)
                        {
                            ret = serDesComm.IICWrite_Burst(currentChipAddr, (object)(Convert.ToInt32(regAddr) + (i * 256)), splitDatas[i], _mode);
                            if (ret == false)
                            {
                                UIMessageTip.ShowError("Write  0x" + (Convert.ToInt32(regAddr) + (i * 1024)).ToString("X") + " Erro");
                                break;
                            }
                        }
                        continue;
                    }
                    
                    for(int i = 0; i < hexData.Length; i++)
                    {
                        string hexValue = hexData[i].Trim();
                        datas[i] = Convert.ToInt32(hexValue,16);
                    }
                    ret = serDesComm.IICWrite_Burst(currentChipAddr, regAddr, datas, mode);
                    if(ret == false)
                    {
                        UIMessageTip.ShowError("Write  0x" +  Convert.ToInt32(regAddr).ToString("X") + " Erro");
                        break;
                    }
                }
                else if (row[0].ToString().ToLower().Contains("delay")){
                    string[] values = row[9].ToString().Split(',');
                    string dalayTime = "";
                    for(int i = 0;i < values.Length;i++)
                    {
                        dalayTime += values[i].Substring(2);
                    }
                    Thread.Sleep(Convert.ToInt32(dalayTime,16));
                }
            }
            UIMessageTip.ShowOk("Successful");
        }
        private static object[][] SplitArray(object[] array, int chunkSize)
        {
            int totalChunks = (array.Length + chunkSize - 1) / chunkSize; // 计算总的数组数量
            object[][] result = new object[totalChunks][];

            for (int i = 0; i < totalChunks; i++)
            {
                int start = i * chunkSize;
                int length = Math.Min(chunkSize, array.Length - start); // 确定每个子数组的长度
                object[] chunk = new object[length];
                Array.Copy(array, start, chunk, 0, length);
                result[i] = chunk;
            }

            return result;
        }

        private void btn_burstRead_Click(object sender, EventArgs e)
        {
            //byte _chipAddr = (byte)(this.txtbox_IICAddr.Text.ToInt() * 2);
            byte _chipAddr = 0;
            string hexInput = this.txtbox_burstRead_IIC_Address.Text;

            // 移除 "0x" 前缀（如果存在）
            if (hexInput.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
            {
                hexInput = hexInput.Substring(2);
            }

            // 验证输入是否为有效的十六进制字符串
            if (IsHexString(hexInput) && hexInput != "")
            {
                // 将十六进制字符串转换为整数，并乘以 2，再转换为字节
                _chipAddr = (byte)(Convert.ToInt32(hexInput, 16) * 2);
                // 这里可以使用 _chipAddr 进行后续操作
            }


            object regAddr = this.numric_Address_BurstRead.Value;
            int count = txtbox_Count.Text.ToInt();

            IICMode mode = IICMode.A16D8;
            object[] rdData;
            bool ret = serDesComm.IICRead_Burst(_chipAddr, regAddr, out rdData, count, mode);                        
        }
    }
}
